package com.cloud.cloudzuul.filter;

import com.cloud.cloudcommons.Redis.RedisLock;
import com.cloud.cloudcommons.Redis.RedisPersistent;
import com.cloud.cloudcommons.Redis.RedisUtil;
import com.cloud.cloudcommons.md5.MD5;
import com.netflix.discovery.converters.Auto;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.sun.org.apache.regexp.internal.RE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Collections;
import java.util.Map;

/**
 * @Aurher: QiaoHang
 * @Description:
 * @Data: 2019/9/17 9:06
 * @Modified By:
 */
@Component
public class MyZuulFilter extends ZuulFilter implements CommandLineRunner {

    //buket令牌凭证
    public static  Long  buketCredentail;

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String uri = request.getRequestURI();               // cloud-common/hi
        String url = request.getRequestURL().toString();    // http://localhost/cloud-common/hi
        if(uri.contains("hi")){
            //请求秒杀接口，进行限流
            return true;
        }
        return false;
    }

    @Override
    public Object run() throws ZuulException {
        System.out.println("filtering...........................");
        //获取上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpSession session = request.getSession();
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            return null;
        }
        //添加请求头
        ctx.addZuulRequestHeader("zuul-header-name","zuul-addHeader-qiaohang");
        //尝试获取令牌，进行限流
        Jedis jedis = RedisUtil.getConnection();
        try {
            String luaScript=  "if redis.call('get' , KEYS[1]) > ARGV[1] then return redis.call('decr',KEYS[1]) else return 0 end";
            Long res = (Long) jedis.eval(luaScript, Collections.singletonList(RedisPersistent.BUKET_CREDENTAIL_GENERATOR),Collections.singletonList("0"));
            //这里返回的是decr的结果（max-incr:99 , min-decr:0 ，因而限流力度：98）
            if(res.intValue()>0){
                //获取到执行资格，添加请求头
                String encoder = MD5.md5("2019xltc", "xltc2019");
                ctx.addZuulRequestHeader("Can-Excutor",encoder);
            }
        }catch (Exception e){
            jedis.close();
        }finally {
            jedis.close();
        }
        return null;
    }

    @Override
    public void run(String... args) throws Exception {
        //key : LOCK_BUKET_CREDENTAIL_GENERATOR     令牌key
        //value : 100                             最大限流数值
        //每次启动后创建并初始化令牌key
        Jedis jedis = RedisUtil.getConnection();
        jedis.set(RedisPersistent.BUKET_CREDENTAIL_GENERATOR,"0");
        jedis.close();
        while (true){
            //每隔一定时间下发令牌key (最多闲置令牌为99)
            String luaScript=  "if redis.call('get' , KEYS[1]) < ARGV[1] then return redis.call('incr',KEYS[1]) else return 0 end";
            Long res = (Long) jedis.eval(luaScript, Collections.singletonList(RedisPersistent.BUKET_CREDENTAIL_GENERATOR),Collections.singletonList(RedisPersistent.MAX_LIMITED_STREAM));
            if(res.intValue() == 0){
                System.out.println("桶满了，暂停发放");
                //当前桶中令牌较多，暂停发放。。。
                Thread.sleep(100);
            }else {
                System.out.println("发放一个,当前桶中数量："+res);
            }
        }
    }
}
